<?php

/* BEGIN License Block %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 *
 * Version: EPL 1.0
 *
 * The contents of this file are subject to the Eclipse Public License Version
 * 1.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *
 * http://www.opensource.org/licenses/eclipse-1.0.txt
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * Copyright (C) 2009 Benry Yip <benryyip@mail.utexas.edu>
 * 
 * END License Block %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

class LeafGCal {

    protected $debug;    // Boolean: turns debug output on and off.
    
    protected $timezone; // String: set local timezones.
                         // Supported timezones: http://us2.php.net/timezones.

    protected $feedURL;  // String: URI of XML feed.

    /* LeafGCal constructor.
     *
     * Defaults ---
     *
     *     Debug Mode: Off
     */
    function __construct($timezone, $debug = false) {

        $this->timezone = $timezone;
        $this->debug = $debug;

        $this->dprint("New LeafGCal object created.");
    }

    /* Generates the XML feed URI for the given calendar.
     *
     * Defaults ---
     *
     *     Display: 7 days
     *     Sort Order: Ascending
     */
    function generateFeedURL($userID, $calendar, $days = 7, $sortorder = "ascending") {

        $this->dprint("Generating Feed URI.");
        
        // GCal API requires RFC3339 for its date parameters.
        $this->currentDate = date(DATE_RFC3339);
        $this->endDate = date(DATE_RFC3339,
                        mktime(date("H"), date("i"), date("s"),
                               date("n"), date("j") + $days, date("Y")));

        $feedURL = "http://www.google.com/calendar/feeds/$userID/$calendar/full" .
                   "?start-min={$this->currentDate}" .
                   "&start-max={$this->endDate}&singleevents=true" .
                   "&orderby=starttime&sortorder=$sortorder" .
                   "&alt=rss&strict=true";

        // If debugging, turn on pretty printing for easy inspection of feed.
        $feedURL .= ($debug ? "$prettyprint=true" : "");
        $this->dprint("Feed URL: $feedURL");
        
        $this->feedURL = $feedURL;
    }

    /* Generates HTML for the list of upcoming events.
     */
    function generateEventList() {

        // HTML templates for dynamic generation.
        $basename           = "leaf-gcal"; # Be sure to change this in dprint() as well.
        
        $openEventOpen      = "<div class=\"$basename-event\" id=\"$basename-event-id-";
        $openEventClose     = "\">\n";
        $closeEvent         = "</div>\n\n";

        $openAttributeOpen  = "\t<p class=\"$basename-event-";
        $openAttributeClose = "\">";
        $closeAttribute     = "</p>\n";
        
        $this->dprint("Generating event list.");

        // If $feedURL is empty, then obviously we haven't generated it.
        if(strlen($this->feedURL) == 0) {
            
            exit("<h1>Make sure to call createFeedURL() before generateEventList()!</h1>");
        }
        
        $reader = new XMLReader();
        
        if($reader->open($this->feedURL)) {
            
            // Only read in XML nodes if we are inside of an event node.
            $inItem = false;
            $count = 0;
            
            while($reader->read()) {
                
                // Are we inside of an <item>?
                if($reader->nodeType == XMLReader::ELEMENT &&
                   $reader->localName == "item") {
                    
                    $inItem = true;
                    
                    echo $openEventOpen . $count . $openEventClose;
                }
                
                // We're inside of an <item> block!
                if($inItem) {
                    
                    if($reader->nodeType == XMLReader::ELEMENT &&
                       $reader->localName == "title") {
                        
                        $reader->read();
                        $title = $reader->value;
                        
                        if(strlen($title) != 0) {
                            
                            $attribute = "title";
                            echo $openAttributeOpen . $attribute . $openAttributeClose .
                                $title             . $closeAttribute;
                        }
                    }
                    
                    if($reader->nodeType == XMLReader::ELEMENT &&
                       $reader->localName == "description") {
                        
                        $reader->read();
                        $description = $reader->value;
                        
                        if(strlen($description) != 0) {
                            
                            $attribute = "description";
                            echo $openAttributeOpen . $attribute . $openAttributeClose .
                                $description       . $closeAttribute;
                        }
                    }
                    
                    // Generate event time.
                    if($reader->nodeType == XMLReader::ELEMENT &&
                       $reader->localName == "when") {
                        
                        $startTime = $reader->getAttribute("startTime");
                        
                        // GCal's feed only gives us a YYYY-MM-DD if the event
                        // is an all-day event.
                        if(strlen($startTime) > 10) {
                            
                            //           111111111 222222222
                            // 012345678 012345678 012345678
                            // 2009-03-27T19:00:00.000-05:00
                            $year   = intval(substr($startTime, 0, 4));
                            $month  = intval(substr($startTime, 5, 2));
                            $day    = intval(substr($startTime, 8, 2));
                            
                            $hour   = intval(substr($startTime, 11, 2));
                            $minute = intval(substr($startTime, 14, 2));
                            
                            $second = 0;
                            
                            $startTimeEpoch = mktime($hour, $minute, $second, $month, $day, $year);
                            
                            $startTime = date('F j, Y, g:ia', $startTimeEpoch);
                            
                            $attribute = "time";
                            echo $openAttributeOpen . $attribute . $openAttributeClose .
                                $startTime         . $closeAttribute;
                            
                        } else {
                            
                            $attribute = "time";
                            echo $openAttributeOpen . $attribute . $openAttributeClose .
                                "All Day"          . $closeAttribute;
                        }
                    }
                    
                    // Generate event location.
                    if($reader->nodeType == XMLReader::ELEMENT &&
                       $reader->localName == "where") {
                        
                        $location = $reader->getAttribute("valueString");
                        
                        if(strlen($location) > 0) {
                            
                            $attribute = "location";
                            echo $openAttributeOpen . $attribute . $openAttributeClose .
                                $location          . $closeAttribute;
                        }
                    }
                }
                
                // Clear out $inItem once we we find the </item> tag.
                if($inItem &&
                   $reader->nodeType == XMLREADER::END_ELEMENT &&
                   $reader->localName == "item") {
                    
                    echo $closeEvent;
                    
                    $inItem = false;
                    
                    $count++;
                }
            }
        }
        
        $reader->close();
    }
    
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRIVATE
    
    /* Prints out debug messages if debug mode is enabled.
     */
    private function dprint($message) {

        $openDebug  = "<h3 class=\"leaf-gcal-debug\">";
        $closeDebug = "</h3>\n\n";

        if($this->debug) {
            echo $openDebug . $message . $closeDebug;
        }
    }
}

?>